{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## QuadMesh"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 四边形网格的数据结构"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "import numpy as np\n",
    "\n",
    "from scipy.sparse import coo_matrix, csr_matrix\n",
    "from scipy.sparse import triu, tril\n",
    "\n",
    "from matplotlib.collections import LineCollection\n",
    "\n",
    "from fealpy.mesh.Mesh2d import Mesh2d\n",
    "from fealpy.mesh.StructureQuadMesh import StructureQuadMesh"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "网格是有限元算法的基础, 最少需要两个二维数组来存储网格的信息:\n",
    "\n",
    "* 网格节点坐标数组 `node`:\n",
    "    + $NN\\times 2$ 的二维数组\n",
    "    + `node[i, 0]` 和 `node[i, 1]` 分别存储第 $i$ 个网格节点的 $x$ 和 $y$ 坐标\n",
    "* 单元顶点编号数组 `cell`:\n",
    "    + $NC\\times 4$ 的二维数组\n",
    "    + `cell[i, 0]`, `cell[i, 1]`, `cell[i, 2]` 和 `cell[i, 3]` 分别存储第 $i$ 个单元四个顶点的全局编号(即 `node` 中的行号)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAAQYAAAEICAYAAAC9P1pMAAAABHNCSVQICAgIfAhkiAAAAAlwSFlz\nAAALEgAACxIB0t1+/AAAGmVJREFUeJzt3Huc1XW97/HXZ82sxR2HywwzDIizYRwB85KUZUoG4gXC\nY2Hbygg7p33Stu7dxepoeqSiY5mZtdvm3tsuHDp1MklCwR4SeEUj2akoIzQzwMQMw0VucpvLWr/v\n/mPNwMB3Buay5Mtavp+PB4/Huvx+Pz5fP9/1Xr/v77fQnHOIiLQXC12AiJx6FAwi4lEwiIhHwSAi\nHgWDiHgUDCLiUTBIxpjZDWb2fOg6pPcUDCLiUTCIiEfB8A5iZpvM7CtmtsbMDpjZT81shJk9YWb7\nzOyPZjakddv3mdkLZrbHzF41s0vbHecGM9vQus9GM7v+mL/nXjPb3freVSd5mJIBCoZ3nlnANOBM\nYCbwBHA7UEh6PvyTmZUCS4B5wFDgVmChmRWa2QDgR8BVzrlBwEXAK+2OfyGwHhgO3AP81MzsZAxM\nMkfB8M7zL865bc65euA5YJVz7mXnXCPwKHA+8ClgqXNuqXMucs4tA1YD01uPEQFnm1k/51yDc25t\nu+PXOuf+wzmXAuYDJcCIkzU4yQwFwzvPtnaPD3XwfCAwBvhY6zJij5ntAS4GSpxzB4DrgBuBBjNb\nYmZntTvG1rYHzrmDrQ8Hvg3jkLdR0GAwsz6t69za1vXqK7myJjWzM8xsaetae6uZ/djM8kPX1UWb\ngQXOuYJ2fwY4577T+v5twCVAPullyV9CFZpJZnazma02syYz+0W71xNm9kjrNRrX/npLtujufAx9\nxpBPehJ+EDgNuAN42MzOCFhTpjwA7CB9Kn0e6TF+PmhFXfdLYKaZXWFmeWbW18wuNbNRZjYCGAZ8\nCRgM3A28FLLYDNpC+rrKzzp473nSS6ytHbyXDbo1H4MGg3PugHNurnNuU+ta9nFgI3BByLoypAz4\njXOu0Tm3FfgDMDFwTV3inNsM/DfSFyV3kA7vr5CeLzFgNHAvsIv0BLspTKWZ5Zz7nXNuEbDzmNeb\nnXP3O+eeB1Jhquu1bs3HU+rUtvXb6Exg7Ym2zQL3A9eZ2dPAEOAq4M6QBTnnzjjm+aeOef4Q8FDr\n41WkP/QeM3uF9KQyIA4UAZXOuV8AvzjmmLojcWro1nwMvZQ4zMziwP8D5jvn1oWuJwOeBc4G3gLq\nSF/VXxS0osz5GvB3QCnw78BjZjY2bElyAt2aj6dEMJhZDFgANAM3By6n11rH8wfgd8AA0vf0hwDf\nDVlXpjjnVjnn9jnnmpxz84GVHLmVKaeYnszH4MHQ+uOXn5K+1z3LOdcSuKRMGAqcDvy49cOzE/g5\nufvhcaSXFXJq6vZ8DB4MwE+A8cBM59yh0MVkgnPuTdIXUW80s3wzKwDmAGvCVtZ7ZlbQereib+vY\nrgcmk/5Gymqt4+kL5AFtd2PyW9/r0/oeQKL1vawIw57MRwv2f4k2c7XAGaS7kK2Xeg+bDFzKkaht\nIP1RqQeSgWrKgDuAuaR7BOlbFNNJz6jmQDVlxLH9AlhBeiWe5Y7tGc6ZmZ1H+gLkuaQ/biuAW5xz\n2zo6RtBgAGjqH2fhT2ZQNS27r12tr61h4fIlNCePrIQS+XFmTZ1BxZjsHVv5shpmfX4JfQ4cGVcu\n9CxX+wUd9KwHd4aCLSVSpCdY/btLqJ5SFqqMjCkfXUZpUQmJ/DiQnmSlRSWUj87usVVPKaP+/BKa\n+sdzqme52i84umek/11LtwU7Y7jDzE2Yfw3VU8pweafCpY7ei6KIqs0b2bpzB8XDCikfXUYslv1j\ns1TEuBUbqZyziFzqWa72C4707JNzFt2Jc/O6vX+oYDAzN3fLl4P83dIzc0d+H/Usu9xVcm+PLpDm\nRjyKSEYpGETEo2AQEY+CQUQ8CgYR8SgYRMSjYBARj4JBRDwKBhHxKBhExKNgEBGPgkFEPAoGEfEo\nGETEo2AQEY+CQUQ8CgYR8SgYRMSjYBARj4JBRDwKBhHxKBhExKNgEBGPgkFEPAoGEfEoGETEo2AQ\nEY+CQUQ8CgYR8SgYRMSjYBARj4JBRDwKBhHxKBhExKNgEBGPgkFEPAoGEfEoGETEo2AQEY+CQUQ8\nCgYR8SgYRMSTH7qAVT97mVceXsv2dW9y9jVn8ZH7rwxdUkbk6rgAFt68lA3P1dJyKMnAogF84KZJ\nXHD9OaHL6rVcHReAmT0NvA9Itr5U75yr6Gz74MEwqHggk//5QmqeqaWlMXniHbJEro4L4OKb38vM\ne6aR6B9nR9VOfnHtw5S8awQjzxkRurReydVxtXOzc+6hrmwYfCkxYXo5468qp9+QvqFLyahcHRfA\niLOGk+gfB8DMMDN2bdoTuKrey9Vx9UTwM4Zc0bd5D6N2rWbEvjfIi5pJxRJsGzSeZ1KhK3t7PH7b\nH3nlN2tJNiYpPruI8qlloUvqls769eP7mlj9SHXWjusE7jaz7wDrga87557ubEMFQwYM3b+RCVsW\nYy4iRgRAftRMyd7XKNnjONAyOnCFmffhuy9j+rwpbF69hU0v1pGfyAtdUpcdr1/zPhvj9a/P5NV1\niawb1wl8DagEmoGPA4+Z2XnOuZqONg63lJgM62triKIoWAmZ0Ld5DxO2LCbPJQ9PsjYxImI4Cg5u\npm9z9p6SRlHE+toar2exvBhjLhzFWw37eGn+q4Gr7JoT9SvPJTl722NUnD8wq8Z1rLae2TfsTgDn\n3Crn3D7nXJNzbj6wEpje2f7hguFSWLh8CQuWLszqcBi1azXmTlS/Y9Su1SelnkyLoogFSxeycPmS\nTnsWJSN212ZH8HWlX+YiRu1anVXjau+onsHcTjZzgHV2jHDBEIPmZAt1DVtYV12NSzlcKqKlMUkq\nmT1BMWLfG943D0AqBc3NEEXgIhjyZmVWjatN1eaN1G9voDnZku7Znhb+9sd6KtdXEaUiqp/exOuL\n1lF28emhS+2Szvq1ezesWAGHDoFLRfxt+dqsGld7R/UMYmZWYGZXmFlfM8s3s+uBycAfOjtG8GsM\nLSuSPHzXY4efr1n4Bh/80vv50K0XBayq6/Ki5g5fX7AA5s8/8nzZshY++KU/Zc242mzdub1tgqUZ\npFalWLTkCRbbkxSMGsyV3/wQZ10xLlyR3dBZv8zg97+H++4D52DEiCRXfnNa1oyrPa9nEAfmAWcB\nKWAdcI1z7q+dHSN4MCSmxZn1nRlUjBkbupQeScUS5Hcw2W64If2nTTKWYGV5doUCQPGwIhL58SMT\nbQAk/iHOrKnZ2bPO+lVQAD/84ZHn6X5l54+bju2Zc24H8J7uHCPcUiKCRH6c0qISykdn7y2hbYPG\nE53gP2NEjG2Dxp+kijKrfHQZpUUlJPLjOdGzXO8XHNMzOlg3dUG4YHgaZk2dwezps4jFgv/Oqsfq\nhk7C2fHrdxajbuikk1RRZsViMWZPn8WsqTNyome53i84pmdwV4+OkdmSuuFZqBgzNmsnWJvGRAGV\nI68mZfneN1FEjJTlUznyahoTBYEq7L1YLJZeNuRAz94J/YIjPXN3uXk92T/4NYZcsGtgGavPmNPh\nL+nqhk7K+kmWa9SvE1MwZEhjooDq4suoLr4sdCnSBerX8WXvOaGIvG0UDCLiUTCIiEfBICIeBYOI\neBQMIuJRMIiIR8EgIh4Fg4h4FAwi4lEwiIhHwSAiHgWDiHgUDCLiUTCIiEfBICIeBYOIeBQMIuJR\nMIiIR8EgIh4Fg4h4FAwi4lEwiIhHwSAiHgWDiHgUDCLiUTCIiEfBICIeBYOIeBQMIuJRMIiIR8Eg\nIh4Fg4h4FAwi4lEwiIhHwSAiHgWDiHgUDCLiUTCIiCc/dAGrfvYyrzy8lu3r3uTsa87iI/dfGbqk\njPj2uB8d9TzZmOQ9c85l+renBqoos3Zu2M0DU+czYcaZzPrx9NDlZMTx5uKG52pZcvty9tbvY9S7\nS7jm/ispGDU4YLVdZ2b7j3mpH/CAc+6WzvYJHgyDigcy+Z8vpOaZWloak6HLyZivV//T4cdNB5q5\n99wHmTCzImBFmbXk9uWUnlscuoyM6mwuHth5kN98djFX33s5Z04by1P3rOS3Nz7OPzz+yYDVdp1z\nbmDbYzMbCGwFfnu8fYIvJSZML2f8VeX0G9I3dClvmzeWVDFgeH/GXFgaupSMeG3ROvqe1oeyi08P\nXUpGdTYX33iimsIzhzFxZgXxvvlceutFbKvcwY6qnYEq7ZVZwHbgueNtFDwY3gle+e1azr12AmYW\nupRea9zXxFP3vsAVd10aupSTZsf6NymeWHT4eaJ/nKFnFLDjr1kZDHOA/+ucc8fbSMHwNttT9xa1\nL9Zx3t9PDF1KRjx1z0re/fGzOW3koNClnDTNB1roMyhx1Gt9BiZo2t8cqKKeMbMxwAeB+SfaNlgw\n3AGUL6vBUlGoEjIuiiLW19bwzF9eZH1tDVEU8eojlZz+3lKGnH5a6PJ6zFIR5ctq+CxQ90Q17/8f\n54cuKSM66ldHEgPiXgg07muiz8BEh9ufCtp6htmd7V6eDTzvnNt4ov2DXXycCyQ/v4T680v45a9n\nhSojY6IoYsHShdRvb6A52UIiP05pUQl7f/sWF9/83tDl9ZilIj71iYWUvtzAVuBXW/bxk7N+TGNB\nX5oOtOAix4OXL+DGJ2eHLrVbOuvX7On+XCysGM6rD689/Lz5YAu7a/dSeOawk1lyl7XvGemP2rda\n3/o08J2uHCPYGUMe0OdACyP+cwun/6Eal3K4VERLY5JUMvvOIqo2bzw8yQCaky1sXl3P3oZ9TMzi\nuxHjVmyk9OUG+hxo4UagBlidH+O7d0xm0uxzKJ9axuwsDPaO+lXXsIV11f5cHH/VOLavf5PKJX+l\npTHJ099/gRETCiksPzWDoX3PaP2Mm9lFQCknuBvRxk5wDeLtY+YA/jdH4iyrTQYu5eioXQzUkb4G\nnKXuIP2Vk9futRRwF/DtEAVlSkf9WgE8G6SajPJ65pyZ2b8B/Z1zXTq1Cx4MTf3jLPzJDKqmjQ1T\nR4asr61h4fIlh7+BABL5cWZNnUHFmOwdW/myGmZ9fknbtw+QGz3L1X5BBz1zrtu3w4ItJVKkJ1j9\nu0uonlIWqoyMKR9dRmlRCYn8OMDhNWv56OweW/WUMurPL6Gpfzynepar/YKjewb0aF0e7IzhDjM3\nYf41VE8pw+Xlxl3TKIqo2ryRrTt3UDyskPLRZcRi2T82S0WMW7GRyjmLyKWe5Wq/4EjPPjln0Z04\nN6/b+4cKBjNzc7d8OcjfLT0zd+T3Uc+yy10l9/boV3W5EY8iklEKBhHxKBhExKNgEBGPgkFEPAoG\nEfEoGETEo2AQEY+CQUQ8CgYR8SgYRMSjYBARj4JBRDwKBhHxKBhExKNgEBGPgkFEPAoGEfEoGETE\no2AQEY+CQUQ8CgYR8SgYRMSjYBARj4JBRDwKBhHxKBhExKNgEBGPgkFEPAoGEfEoGETEo2AQEY+C\nQUQ8CgYR8SgYRMSjYBARj4JBRDwKBhHxKBhExKNgEBGPgkFEPPmhCzi4+xCLv/wkNc9sov/Qfky9\n7RLO+ej40GX1Wq6OK9mUZMlty9nwXC2H9jQyZEwBl91+CeVTykKX1iu5Oq72zKwceA14xDn3qeNt\nGzwYlt6+nLx4jFvX3MTW17fzq08/SvHEQooqhocurVdydVxRyjF45CBu+N11nFY6mKrlG/jt5x7j\nphVzGDL6tNDl9ViujusY/wq81JUNgy4lmg+2ULm0ig999QP0GZBgzIWjqLhiHK8+UhmyrF7L1XEB\nJPrH+dCtFzFk9GnEYkbFtLEUnH4aDWu2hS6tV3J1XG3M7OPAHmB5V7YPesaws2YXsbwYw8cOPfxa\n8YRCNr2wOWBVPdO3eQ+jdq1mxL432LC+mXgM3jfgL9Q1T6IxUZC14zqR/TsOsHPDbgrPHBa6lG5p\n36+8qJlULMG2QeOpG5ruV7aOqyNmNhj4JjAF+GxX9gkaDM0HW+gzKHHUa30GJWg60Byoop4Zun8j\nE7YsxlxEjIjGQ9C/P5TsfY3it9ZSOfLqrBzXiaRaUiz8x6Wc97GJFJZnzwfo2H4B5EfNh/v1WuGH\nmf+Pf8m6cR3Ht4CfOufqzKxLO4RbSkyGLXu30bTv6A9L41tN9BmQ6GSnU0/f5j1M2LKYPJc8PMn6\n9YODByFGRJ5LMmHLYlK792bVuNqLooj1tTUwGdbX1hBFEVHk+N0tT5CXyGP6t6eELrHLOupXmxgR\nlkry+5t/TyI/yqpxHautZ3ad/StwGfCD7uwf7ozhUlix4XmSLUl2VO+kcFw6mbdV7qCwIntSetSu\n1Zg7eoKNGgWpFNTVpR+bi9j7ShWFFeMCVdlzURSxYOlC6rc3wKWwcPkSRhYWc9ryQRx48yDXL/gI\nefG80GV2WUf9auMcfO97sHu342sPDOFvWTSu9o7q2V5uAg4Bf2s9WxgI5JnZBOfcuzs7Rrgzhhi0\nxJLEJhiPfWsZzQdbqF1Vx/onazj32gnByuquEfve8L55+vWDSy6Bn/8cDh2Cta9FvPzM7qwaV5uq\nzRup395Ac7IFYtCcbOFvD9VTt7aBT8y/hni/eOgSu6WjfrX5wQ+gthbu/j8wumX9Sa4sc47q2QUY\nMBY4r/XPg8AS4IrjHSP47croKsfBZw/xvXc9QL8h/Zhx92VZdUsvL+r4usEXvgD33AMf/SgMHgxf\n/ALEs2hcbbbu3J6eYG32QPRSxO74Hu4998HDL8+8Z1pW/E6js35t3QqPPQbxeLpn0Ewq9qOsGVd7\nR/UsAc65rW3vmdl+oNE5t+N4xwgeDInBcab9YDIVY8aGLqVHUrEE+R1MtsGDYd68I8+TsQQrT2Jd\nmVI8rIhEfvzIRCuAxLw4s6bOyMqeddav4mJ46qkjz5OxBCvLbzmJlWWO17N2nHNzu3KMcEuJCBL5\ncUqLSigfnb2/Lts2aDzRCf4zRsTYNii7vnXalI8uo7SohER+PCd6luv9gmN6RifrphMIFwxPw6yp\nM5g9fRaxWPb+k426oZNwdvz6ncWoGzrpJFWUWbFYjNnTZzFr6oyc6Fmu9wuO6Rnc1aNjZLakbngW\nKsaMzdoJ1qYxUUDlyKtJWb73TRQRI2X5VI68msZEQaAKey8Wi6WXDTnQs3dCv+BIz9xdbt6Jt/YF\nv8aQC3YNLGP1GXOO+0s6OXWoXyemYMiQxkQB1cWXUV18WehSpAvUr+PL3nNCEXnbKBhExKNgEBGP\ngkFEPAoGEfEoGETEo2AQEY+CQUQ8CgYR8SgYRMSjYBARj4JBRDwKBhHxKBhExKNgEBGPgkFEPAoG\nEfEoGETEo2AQEY+CQUQ8CgYR8SgYRMSjYBARj4JBRDwKBhHxKBhExKNgEBGPgkFEPAoGEfEoGETE\no2AQEY+CQUQ8CgYR8SgYRMSjYBARj4JBRDwKBhHxKBhExKNgEBGPgkFEPPmhCzi4+xCLv/wkNc9s\nov/Qfky97RLO+ej40GVlxGuL1vHMfS+yt/4tBhYN4Jr7r2TMhaNCl9VrC29eyobnamk5lGRg0QA+\ncNMkLrj+nNBl9dqOqp0suX05DWu20X9Yfy6/czLjryoPXVbGmNnHgbuA04GtwA3Ouec62jZ4MCy9\nfTl58Ri3rrmJra9v51effpTiiYUUVQwPXVqv1DyziT9++1muffDDlJ5fwv5t+0OXlDEX3/xeZt4z\njUT/ODuqdvKLax+m5F0jGHnOiNCl9VgqGfHrz/yeSbPP4dP//1o2vVjHr+c8yueenM3wsUNDl9dr\nZjYN+C5wHfBnoOR42wddSjQfbKFyaRUf+uoH6DMgwZgLR1FxxThefaQyZFkZ8dS9L/DBL76f0ReM\nJBYzBpcMYnDJoNBlZcSIs4aT6B8HwMwwM3Zt2hO4qt55s3oX+7bu5/3/8wJieTH+7uLTGf2eUtYs\nfCN0aZnyDeCbzrk/Oeci51y9c66+s42DnjHsrNlFLC92VCIXTyhk0wubA1bVe1EqYsuabVRcPpYf\nXvRTkk1JzrpiHJffOZl4v3jo8jLi8dv+yCu/WUuyMUnx2UWUTy0LXVLmOcf2dW+GrqLXzCwPmAQs\nNrNqoC+wCPiKc+5QR/sEP2PoMyhx1Gt9BiVoOtAcqKLM2L/jIFFLROWSKv77o9dx45Oz2fr6dp79\n4arQpWXMh+++jNurbuEzj17H+Onl5CfyQpfUK8PHDmHA8P6sfOAlUi0pqp/exKY/1dFyqCV0aZkw\nAogD1wKXAOcB5wN3dLZDsGC4Axj32jaa9x0dAo1vNdFnQKLjnU5xURSxvraGP//1ZQDe+5lzGTRi\nIAOG9ef9n7uAquUbAlfYM5aKKF9Wwx1A+bIaLBUBEMuLMebCUbzVsI+X5r8atsgeaOvXM395keot\nm7juoZlULd/Ivec9yIv/tpqJMyuydvnX1jPM7gTazgr+xTnX4Jx7E7gPmN7Z/sGWEnOBvd95nrlN\nSXZV72TouGEAbKvcQWHFsFBl9VgURSxYupD67Q00J1tgMKxcs5pzPzaRWCwGZqFL7BFLRXzqEwsp\nfbmBfCD5+SXUn1/CL389C5eX/l6JkhG7a7PrGsOx/UrkxyktKmHOIx9L9wt4aOavOO/vJwautPva\n9wyY65z7lpnVAa7dZq7jvdOCnTHkAUMPJrkmZrz0lWU0H2yhdlUd65+s4dxrJ4Qqq8eqNm88EgoA\n58HOJ3fz2qvrOLSnkT/9+39y5rSxYYvsgXErNlL6cgN9DrSQB+w90MLKP9czamkVUSqi+ulNvL5o\nHWUXnx661G45tl/NyRY2r9nCuupqmg+2sPInL7F/+4GsDIb2PePIZ/znwC1mVmRmQ4AvAo93dgxz\n7rjB8fYxcwA7IZoC69fAmPRT/pdz7ldhiuo5+4bdSfpEKN2IFPAEjldoIsle4GHgq865xmBF9oQd\nPa4dpBeqq6CxCVqAWuBHzrn/CFZjD3j9AngSx59pIkkKeA64xTlXHabCXjimZzhnZhYHfgh8Emjk\nBPMxXDCIyClLP4kWEY+CQUQ8CgYR8SgYRMSjYBARj4JBRDwKBhHxKBhExKNgEBGPgkFEPAoGEfEo\nGETEo2AQEY+CQUQ8CgYR8SgYRMSjYBARj4JBRDwKBhHxKBhExKNgEBGPgkFEPP8FtTMbg8V3WNsA\nAAAASUVORK5CYII=\n",
      "text/plain": [
       "<matplotlib.figure.Figure at 0x7f75cef194a8>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[[ 6  2  7  0]\n",
      " [ 7  3  8  1]\n",
      " [ 9  4 10  2]\n",
      " [10  5 11  3]]\n"
     ]
    }
   ],
   "source": [
    "%matplotlib inline\n",
    "import matplotlib.pyplot as plt\n",
    "box = [0, 1, 0, 1]\n",
    "n = 2\n",
    "qmesh = StructureQuadMesh(box, n, n)\n",
    "fig = plt.figure()\n",
    "axes = fig.gca()\n",
    "qmesh.add_plot(axes)\n",
    "qmesh.find_node(axes, showindex=True, markersize=25, fontsize=12)\n",
    "qmesh.find_edge(axes, showindex=True, markersize=25, fontsize=12)\n",
    "qmesh.find_cell(axes, showindex=True, markersize=100, fontsize=12)\n",
    "axes.set_title('mesh')\n",
    "plt.show()\n",
    "print(qmesh.ds.cell_to_edge())"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "除了上述两个基本数组之外, 有限元方法中还需要更多的网格数据, 如:\n",
    "\n",
    "* 边数组 `edge`\n",
    "    + 二维 $NE\\times 2$ 数组 \n",
    "    + `edge[i, 0]` 和 `edge[i, 1]` 分别存储第 $i$ 条边的起点和终点的全局编号(即对应 `node` 数组中的行号)\n",
    "    + 如果第 $i$ 条边是边界边, 则规定从 `edge[i, 0]` 看向 `edge[i, 1]`, 网格离散区域一定在左手边\n",
    "* 边与单元的相邻关系数组 `edge2cell`\n",
    "    + 二维 $NE \\times 4 $ 的数组\n",
    "    + `edge2cell[i, 0]` 和 `edge2cell[i, 1]` 分别存储第 $i$ 条边左右两个单元的全局编号(即对应 `cell` 数组中的行号)\n",
    "    + `edge2cell[i, 2]` 和 `edge2cell[i, 3]` 分别存储第 $i$ 条边在左右两个单元中的局部编号\n",
    "    + 如果是边界边, 则\n",
    "        - `edge2cell[i, 0] = edge2cell[i, 1]` \n",
    "        - `edge2cell[i, 2] = edge2cell[i, 3]`\n",
    "        \n",
    "**注: `edge` 和 `edge2cell` 可以从 `cell` 中构造出来.**"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[ 0. ,  0. ],\n",
       "       [ 0. ,  0.5],\n",
       "       [ 0. ,  1. ],\n",
       "       [ 0.5,  0. ],\n",
       "       [ 0.5,  0.5],\n",
       "       [ 0.5,  1. ],\n",
       "       [ 1. ,  0. ],\n",
       "       [ 1. ,  0.5],\n",
       "       [ 1. ,  1. ]])"
      ]
     },
     "execution_count": 4,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "qmesh.node"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[0, 3, 4, 1],\n",
       "       [1, 4, 5, 2],\n",
       "       [3, 6, 7, 4],\n",
       "       [4, 7, 8, 5]], dtype=int32)"
      ]
     },
     "execution_count": 7,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "qmesh.entity('cell')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[0, 0, 3, 3],\n",
       "       [1, 1, 3, 3],\n",
       "       [0, 2, 1, 3],\n",
       "       [1, 3, 1, 3],\n",
       "       [2, 2, 1, 1],\n",
       "       [3, 3, 1, 1],\n",
       "       [0, 0, 0, 0],\n",
       "       [1, 0, 0, 2],\n",
       "       [1, 1, 2, 2],\n",
       "       [2, 2, 0, 0],\n",
       "       [3, 2, 0, 2],\n",
       "       [3, 3, 2, 2]], dtype=int32)"
      ]
     },
     "execution_count": 9,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "qmesh.ds.edge_to_cell()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 28,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[ 0,  0,  3,  3],\n",
       "       [ 1,  1,  3,  3],\n",
       "       [ 2,  2,  3,  3],\n",
       "       [ 3,  3,  3,  3],\n",
       "       [ 0,  4,  1,  3],\n",
       "       [ 1,  5,  1,  3],\n",
       "       [ 2,  6,  1,  3],\n",
       "       [ 3,  7,  1,  3],\n",
       "       [ 4,  8,  1,  3],\n",
       "       [ 5,  9,  1,  3],\n",
       "       [ 6, 10,  1,  3],\n",
       "       [ 7, 11,  1,  3],\n",
       "       [ 8, 12,  1,  3],\n",
       "       [ 9, 13,  1,  3],\n",
       "       [10, 14,  1,  3],\n",
       "       [11, 15,  1,  3],\n",
       "       [12, 12,  1,  1],\n",
       "       [13, 13,  1,  1],\n",
       "       [14, 14,  1,  1],\n",
       "       [15, 15,  1,  1],\n",
       "       [ 0,  0,  0,  0],\n",
       "       [ 1,  0,  0,  2],\n",
       "       [ 2,  1,  0,  2],\n",
       "       [ 3,  2,  0,  2],\n",
       "       [ 3,  3,  2,  2],\n",
       "       [ 4,  4,  0,  0],\n",
       "       [ 5,  4,  0,  2],\n",
       "       [ 6,  5,  0,  2],\n",
       "       [ 7,  6,  0,  2],\n",
       "       [ 7,  7,  2,  2],\n",
       "       [ 8,  8,  0,  0],\n",
       "       [ 9,  8,  0,  2],\n",
       "       [10,  9,  0,  2],\n",
       "       [11, 10,  0,  2],\n",
       "       [11, 11,  2,  2],\n",
       "       [12, 12,  0,  0],\n",
       "       [13, 12,  0,  2],\n",
       "       [14, 13,  0,  2],\n",
       "       [15, 14,  0,  2],\n",
       "       [15, 15,  2,  2]], dtype=int32)"
      ]
     },
     "execution_count": 28,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "tmesh.edge2cell"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 31,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[20,  4, 21,  0],\n",
       "       [21,  5, 22,  1],\n",
       "       [22,  6, 23,  2],\n",
       "       [23,  7, 24,  3],\n",
       "       [25,  8, 26,  4],\n",
       "       [26,  9, 27,  5],\n",
       "       [27, 10, 28,  6],\n",
       "       [28, 11, 29,  7],\n",
       "       [30, 12, 31,  8],\n",
       "       [31, 13, 32,  9],\n",
       "       [32, 14, 33, 10],\n",
       "       [33, 15, 34, 11],\n",
       "       [35, 16, 36, 12],\n",
       "       [36, 17, 37, 13],\n",
       "       [37, 18, 38, 14],\n",
       "       [38, 19, 39, 15]], dtype=int32)"
      ]
     },
     "execution_count": 31,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "tmesh.cell_to_edge()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 34,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[ 0,  4,  1,  0],\n",
       "       [ 0,  5,  2,  1],\n",
       "       [ 1,  6,  3,  2],\n",
       "       [ 2,  7,  3,  3],\n",
       "       [ 4,  8,  5,  0],\n",
       "       [ 4,  9,  6,  1],\n",
       "       [ 5, 10,  7,  2],\n",
       "       [ 6, 11,  7,  3],\n",
       "       [ 8, 12,  9,  4],\n",
       "       [ 8, 13, 10,  5],\n",
       "       [ 9, 14, 11,  6],\n",
       "       [10, 15, 11,  7],\n",
       "       [12, 12, 13,  8],\n",
       "       [12, 13, 14,  9],\n",
       "       [13, 14, 15, 10],\n",
       "       [14, 15, 15, 11]])"
      ]
     },
     "execution_count": 34,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "tmesh.cell_to_cell()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 35,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([ 0,  1,  2,  3, 16, 17, 18, 19, 20, 24, 25, 29, 30, 34, 35, 39])"
      ]
     },
     "execution_count": 35,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "tmesh.boundary_edge_index()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Point:\n",
      " [[0.   0.  ]\n",
      " [0.   0.25]\n",
      " [0.   0.5 ]\n",
      " [0.   0.75]\n",
      " [0.   1.  ]\n",
      " [0.25 0.  ]\n",
      " [0.25 0.25]\n",
      " [0.25 0.5 ]\n",
      " [0.25 0.75]\n",
      " [0.25 1.  ]\n",
      " [0.5  0.  ]\n",
      " [0.5  0.25]\n",
      " [0.5  0.5 ]\n",
      " [0.5  0.75]\n",
      " [0.5  1.  ]\n",
      " [0.75 0.  ]\n",
      " [0.75 0.25]\n",
      " [0.75 0.5 ]\n",
      " [0.75 0.75]\n",
      " [0.75 1.  ]\n",
      " [1.   0.  ]\n",
      " [1.   0.25]\n",
      " [1.   0.5 ]\n",
      " [1.   0.75]\n",
      " [1.   1.  ]]\n",
      "Cell:\n",
      " [[ 0  5  6  1]\n",
      " [ 1  6  7  2]\n",
      " [ 2  7  8  3]\n",
      " [ 3  8  9  4]\n",
      " [ 5 10 11  6]\n",
      " [ 6 11 12  7]\n",
      " [ 7 12 13  8]\n",
      " [ 8 13 14  9]\n",
      " [10 15 16 11]\n",
      " [11 16 17 12]\n",
      " [12 17 18 13]\n",
      " [13 18 19 14]\n",
      " [15 20 21 16]\n",
      " [16 21 22 17]\n",
      " [17 22 23 18]\n",
      " [18 23 24 19]]\n",
      "Edge and Edge2cell:\n",
      " [[ 1  0  0  0  3  3]\n",
      " [ 2  1  1  1  3  3]\n",
      " [ 3  2  2  2  3  3]\n",
      " [ 4  3  3  3  3  3]\n",
      " [ 5  6  0  4  1  3]\n",
      " [ 6  7  1  5  1  3]\n",
      " [ 7  8  2  6  1  3]\n",
      " [ 8  9  3  7  1  3]\n",
      " [10 11  4  8  1  3]\n",
      " [11 12  5  9  1  3]\n",
      " [12 13  6 10  1  3]\n",
      " [13 14  7 11  1  3]\n",
      " [15 16  8 12  1  3]\n",
      " [16 17  9 13  1  3]\n",
      " [17 18 10 14  1  3]\n",
      " [18 19 11 15  1  3]\n",
      " [20 21 12 12  1  1]\n",
      " [21 22 13 13  1  1]\n",
      " [22 23 14 14  1  1]\n",
      " [23 24 15 15  1  1]\n",
      " [ 0  5  0  0  0  0]\n",
      " [ 1  6  1  0  0  2]\n",
      " [ 2  7  2  1  0  2]\n",
      " [ 3  8  3  2  0  2]\n",
      " [ 9  4  3  3  2  2]\n",
      " [ 5 10  4  4  0  0]\n",
      " [ 6 11  5  4  0  2]\n",
      " [ 7 12  6  5  0  2]\n",
      " [ 8 13  7  6  0  2]\n",
      " [14  9  7  7  2  2]\n",
      " [10 15  8  8  0  0]\n",
      " [11 16  9  8  0  2]\n",
      " [12 17 10  9  0  2]\n",
      " [13 18 11 10  0  2]\n",
      " [19 14 11 11  2  2]\n",
      " [15 20 12 12  0  0]\n",
      " [16 21 13 12  0  2]\n",
      " [17 22 14 13  0  2]\n",
      " [18 23 15 14  0  2]\n",
      " [24 19 15 15  2  2]]\n",
      "Cell2edge:\n",
      " [[20  4 21  0]\n",
      " [21  5 22  1]\n",
      " [22  6 23  2]\n",
      " [23  7 24  3]\n",
      " [25  8 26  4]\n",
      " [26  9 27  5]\n",
      " [27 10 28  6]\n",
      " [28 11 29  7]\n",
      " [30 12 31  8]\n",
      " [31 13 32  9]\n",
      " [32 14 33 10]\n",
      " [33 15 34 11]\n",
      " [35 16 36 12]\n",
      " [36 17 37 13]\n",
      " [37 18 38 14]\n",
      " [38 19 39 15]]\n"
     ]
    }
   ],
   "source": [
    "qmesh.print()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.6.1"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
